/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#ifndef __NOISE_HARD_SAMSUNG_CHANNEL_H__
#define __NOISE_HARD_SAMSUNG_CHANNEL_H__

#include <FBase.h>
#include <noise/Manager.h>
#include <noise/hard/Channel.h>
#include <math/Vector3.h>
#include <SharedRep.h>
#include <Atom.h>
#include <list>
#include <deque>
#include "AudioOutPool.h"

namespace Osp {
namespace Media {

	class AudioOut;
} // namespace Media
} // namespace Osp

namespace liba {
namespace noise {
namespace hard {
namespace samsung {

class Hardware;

class ChannelStaticRepName
{
public:
	Atom channel_type;
	filesystem::String name;
	Hardware * hardware;

	ChannelStaticRepName(Hardware * hardware, const Atom & channel_type, const filesystem::String & name):
		hardware( hardware ),
		channel_type( channel_type ),
		name( name )
	{}
	bool operator<(const ChannelStaticRepName & na)const
	{
		if( hardware < na.hardware )
			return true;
		if( hardware > na.hardware )
			return false;
		if( channel_type < na.channel_type )
			return true;
		if( channel_type > na.channel_type )
			return false;
		return name < na.name;
	}
};

struct WAV
{
	unsigned short wFormatTag;
	unsigned short nChannels;
	unsigned nSamplesPerSec;
	unsigned nAvgBytesPerSec;
	unsigned short nBlockAlign;
	unsigned short wBitsPerSample;
};

class ChannelStaticRep
{
public:
	WAV wfx;
	float current_max_volume;	//only loudest sound will play from the sounds with the same rep
	Osp::Base::ByteBuffer buffer;
public:
	ChannelStaticRep(const ChannelStaticRepName & name);
	~ChannelStaticRep();
private:
	char * mem;

	AutoPtr<DataSource> source;
};

class Channel : public hard::Channel
{
protected:
	bool loop;
	double exact_volume;
	double min_distance, max_distance;
	double exact_pan;
	math::Vector3<float> exact_position;
	math::Vector3<float> exact_speed;

	virtual bool change_attribute(const Atom & name, const math::Vector3<float> & value);
	virtual bool change_attribute(const Atom & name, double value);
	virtual bool get_attribute(const Atom & name, math::Vector3<float> * value)const;
	virtual bool get_attribute(const Atom & name, double * value)const;
public:
	Channel();
	~Channel();
};

class ChannelStatic :
	public Shared<ChannelStaticRepName, ChannelStaticRep>,
	public Channel,
	public AudioOutEvents

{
	Atom channel_type;
	unsigned position;
	double approx_vol;
	bool finished;
	bool in_existance_flag;
public:
	static bool SortPredicate(ChannelStatic * a, ChannelStatic * b)
	{
		return a->approx_vol > b->approx_vol;
	}
	ChannelStatic(Hardware * ha, const Atom & channel_type, const filesystem::String & name);
	virtual ~ChannelStatic();
	void life_cycle(double delta_time, const math::Vector3<float> & listener_position);
	bool in_existance()const
	{
		return in_existance_flag;
	}
	void come_to_existance();
	void begone();
	virtual void play(DataSource * source);
	virtual void stop();
	virtual bool is_finished();
	void on_hardware_delete();

	void AudioOutEndOfBuffer();
private:
	int buffer_position;
	void prepare_audio_out();
	void write_first_chunk();
	void release_audio_out();
	void update_volume();
	AudioOutHandle audioOut;
};

} // namespace samsung
} // namespace hard
} // namespace noise
} // namesapce liba
using namespace liba;

#endif /* __NOISE_HARD_SAMSUNG_CHANNEL_H__ */
